﻿using Mirror.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Mirror.Strategies
{
    public abstract class Strategy
    {
        public const int SymbolTimeout = 7200;


        public abstract String Name { get; }
        
        public String Login { get; private set; }
        public String Broker { get; private set; }
        public String Symbol { get { return _symbol; } }
        public int MagicNumber { get { return _magicNumber; } }
        public double MinLotSize { get { return _minLotSize; } }
        
        protected abstract int ParametersCount { get; }

        protected abstract bool ParseParameters();

        protected abstract bool CalculateTargetVolume(out double TargetVolume);

        protected String[] _parameters;
        private double _maxVolume;
        private double _volumeDifference;
        private double _minLotSize;
        private int _magicNumber;
        private String _symbol;

        protected List<Symbol> _symbols = new List<Symbol>();

        protected Strategy(StrategySettings settings)
        {
            this.Login = settings.Login;
            this.Broker = settings.Broker;

            this._parameters = settings.Parameters.Split(';');
            this._maxVolume = settings.MaximumVolume;
            this._volumeDifference = settings.VolumeDifference;
            this._minLotSize = settings.MinLotSize;
            this._magicNumber = settings.MagicNumber;
            this._symbol = settings.Symbol;

            foreach (var pair in settings.ProvidersToSymbols)
            {
                Symbol s = ProvidersDownloader.Instance.GetSymbol(pair.Provider, pair.Symbol);
                if (s != null)
                {
                    this._symbols.Add(s);
                }
                else
                {
                    System.Console.WriteLine("Warning: Provider-Symbol ({0},{1}) pair doesn't exist.", pair.Provider, pair.Symbol);
                }
                
            }

            if (ParametersCount != this._parameters.Count())
            {
                throw new ArgumentException("Wrong parameters count.");
            }

            if (!this.ParseParameters())
            {
                throw new ArgumentException("Wrong parameter.");
            }
        }

        public double VolumeDifference
        {
            get
            {
                return _volumeDifference;
            }
        }

        public bool TryGetTargetVolume(out double TargetVolume) {

            bool result = CalculateTargetVolume(out TargetVolume);

            TargetVolume = (TargetVolume > _maxVolume) ? _maxVolume : TargetVolume;

            return result;
        }
        
        public static Strategy GenerateStrategy(StrategySettings settings)
        {
            Strategy strategy;

            switch (settings.StrategyName)
            {
                case "Mirror":
                    strategy = new MirrorStrategy(settings);
                    break;
                default:
                    throw new Exception("Wrong strategy name.");
            }

            return strategy;
        }

    }
}
